home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3.2 / Ham Radio Version 3.2 (Chestnut CD-ROMs)(1993).ISO / packet / n17jsrc / dialer.c < prev    next >
C/C++ Source or Header  |  1991-06-25  |  9KB  |  382 lines

  1. /* Automatic SLIP/PPP line dialer.
  2.  *
  3.  * Copyright 1991 Phil Karn, KA9Q
  4.  *
  5.  *    Mar '91    Bill Simpson & Glenn McGregor
  6.  *        completely re-written;
  7.  *        human readable control file;
  8.  *        includes wait for string, and speed sense;
  9.  *        dials immediately when invoked.
  10.  *    May '91 Bill Simpson
  11.  *        re-ordered command line;
  12.  *        allow dial only;
  13.  *        allow inactivity timeout without ping.
  14.  */
  15. /* mods by PA0GRI */
  16. #include <stdio.h>
  17. #include <ctype.h>
  18. #include "global.h"
  19. #include "config.h"
  20. #include "mbuf.h"
  21. #include "timer.h"
  22. #include "proc.h"
  23. #include "iface.h"
  24. #include "netuser.h"
  25. #include "8250.h"
  26. #include "asy.h"
  27. #include "tty.h"
  28. #include "session.h"
  29. #include "socket.h"
  30. #include "cmdparse.h"
  31. #include "devparam.h"
  32. #include "icmp.h"
  33. #include "files.h"
  34. #include "main.h"
  35. #include "trace.h"
  36.  
  37. #define MIN_INTERVAL    5L
  38.  
  39. static int redial __ARGS((struct iface *ifp,char *file));
  40.  
  41. static int dodial_control    __ARGS((int argc,char *argv[],void *p));
  42. static int dodial_send        __ARGS((int argc,char *argv[],void *p));
  43. static int dodial_speed        __ARGS((int argc,char *argv[],void *p));
  44. static int dodial_wait        __ARGS((int argc,char *argv[],void *p));
  45.  
  46.  
  47. static struct cmds dial_cmds[] = {
  48.     "control",    dodial_control,    0, 2, "control up | down",
  49.     "send",        dodial_send,    0, 2,
  50.     "send \"string\" [<milliseconds>]",
  51.     "speed",    dodial_speed,    0, 2, "speed <bps>",
  52.     "wait",        dodial_wait,    0, 2,
  53.     "wait <milliseconds> [ \"string\" [speed] ]",
  54.     NULLCHAR,    NULLFP,        0, 0, "Unknown command",
  55. };
  56.  
  57.  
  58. /* dial <iface> <filename> [ <seconds> [ <pings> [<hostid>] ] ]
  59.  *    <iface>        must be asy type
  60.  *    <filename>    contains commands which are executed.
  61.  *            missing: kill outstanding dialer.
  62.  *    <seconds>    interval to check for activity on <iface>.
  63.  *    <pings>     number of missed pings before redial.
  64.  *    <hostid>    interface to ping.
  65.  */
  66. int
  67. dodialer(argc,argv,p)
  68. int argc;
  69. char *argv[];
  70. void *p;
  71. {
  72.     struct iface *ifp;
  73.     int32 interval = 0L;        /* in seconds */
  74.     int32 last_wait = 0L;
  75.     int32 target = 0L;
  76.     int pings = 0;
  77.     int countdown;
  78.     char *filename;
  79.     char *ifn;
  80.     int result;
  81.     int s;
  82.  
  83.     if((ifp = if_lookup(argv[1])) == NULLIF){
  84.         tprintf("Interface %s unknown\n",argv[1]);
  85.         return 1;
  86.     }
  87.     if( ifp->dev >= ASY_MAX || Asy[ifp->dev].iface != ifp ){
  88.         tprintf("Interface %s not asy port\n",argv[1]);
  89.         return 1;
  90.     }
  91.  
  92.     if(ifp->supv != NULLPROC){
  93.         while ( ifp->supv != NULLPROC ) {
  94.             alert(ifp->supv, EABORT);
  95.             pwait(NULL);
  96.         }
  97.         tprintf("dialer terminated on %s\n",argv[1]);
  98.     }
  99.  
  100.     if ( argc < 3 ) {
  101.         /* just terminating */
  102.         return 0;
  103.     }
  104.  
  105.     chname( Curproc, ifn = if_name( ifp, " dialer" ) );
  106.     free( ifn );
  107.     filename = rootdircat(argv[2]);
  108.  
  109.     /* handle minimal command (just thru filename) */
  110.     if ( argc < 4 ) {
  111.         /* just dialing */
  112.         result = redial(ifp, filename);
  113.  
  114.         if ( filename != argv[2] )
  115.             free(filename);
  116.         return result;
  117.  
  118.     /* get polling interval (arg 3) */
  119.     } else if ( (interval = atol(argv[3])) <= MIN_INTERVAL ) {
  120.         tprintf("interval must be > %d seconds\n", MIN_INTERVAL);
  121.         return 1;
  122.     }
  123.  
  124.     /* get the number of pings before redialing (arg 4) */
  125.     if ( argc < 5 ) {
  126.     } else if ( (pings = atoi(argv[4])) <= 0 ){
  127.         tprintf("pings must be > 0\n");
  128.         return 1;
  129.     }
  130.  
  131.     /* retrieve the host name (arg 5) */
  132.     if ( argc < 6 ) {
  133.     } else if ( (target = resolve(argv[5])) == 0L ) {
  134.         tprintf(Badhost,argv[5]);
  135.         return 1;
  136.     }
  137.  
  138.     countdown = pings;
  139.     ifp->supv = Curproc;
  140.  
  141.     while ( !main_exit ) {
  142.         int32 wait_for = interval;
  143.  
  144.         if ( Asy[ ifp->dev ].rlsd_line_control == RLSD_DOWN ) {
  145.             /* definitely down */
  146.             if ( redial(ifp,filename) < 0 )
  147.                 break;
  148.         } else if ( ifp->lastrecv >= last_wait ) {
  149.             /* got something recently */
  150.             wait_for -= secclock() - ifp->lastrecv;
  151.             countdown = pings;
  152.         } else if ( countdown < 1 ) {
  153.             /* we're down, or host we ping is down */
  154.             if ( redial(ifp,filename) < 0 )
  155.                 break;
  156.         } else if ( target != 0L
  157.            && (s = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)) != -1 ) {
  158.             pingem(s,target,0,(int16)s,0);
  159.             close_s(s);
  160.             countdown--;
  161.         } else if ( ifp->echo != NULLFP ) {
  162.             (*ifp->echo)(ifp,NULLBUF);
  163.             countdown--;
  164.         }
  165.  
  166.         last_wait = secclock();
  167.         if ( wait_for != 0L ) {
  168.             alarm( wait_for * 1000L );
  169.             if ( pwait( &(ifp->supv) ) == EABORT )
  170.                 break;
  171.             alarm(0L);        /* clear alarm */
  172.         }
  173.     }
  174.  
  175.     if ( filename != argv[2] )
  176.         free(filename);
  177.     ifp->supv = NULLPROC;    /* We're being terminated */
  178.     return 0;
  179. }
  180.  
  181.  
  182. /* execute dialer commands
  183.  * returns: -1 fatal error, 0 OK, 1 try again
  184.  */
  185. static int
  186. redial( ifp, file )
  187. struct iface *ifp;
  188. char *file;
  189. {
  190.     char *inbuf, *intmp;
  191.     FILE *fp;
  192.     int (*rawsave) __ARGS((struct iface *,struct mbuf *));
  193.     struct session *sp;
  194.     int result = 0;
  195.     int save_input = Curproc->input;
  196.     int save_output = Curproc->output;
  197.  
  198.     if((fp = fopen(file,READ_TEXT)) == NULLFILE){
  199.         tprintf("redial: can't read %s\n",file);
  200.         return -1;    /* Causes dialer proc to terminate */
  201.     }
  202.     /* Save output handler and temporarily redirect output to null */
  203.     if(ifp->raw == bitbucket){
  204.         tprintf("redial: tip or dialer already active on %s\n",ifp->name);
  205.         return -1;
  206.     }
  207.  
  208.     /* allocate a session descriptor */
  209.     if ( (sp = newsession( ifp->name, DIAL, 0 )) == NULLSESSION ) {
  210.         tprintf( "Too many sessions\n" );
  211.         return 1;
  212.     }
  213.     tprintf( "Dialing on %s\n\n", ifp->name );
  214.  
  215.     /* Save output handler and temporarily redirect output to null */
  216.     rawsave = ifp->raw;
  217.     ifp->raw = bitbucket;
  218.  
  219.     /* Suspend the packet input driver. Note that the transmit driver
  220.      * is left running since we use it to send buffers to the line.
  221.      */
  222.     suspend(ifp->rxproc);
  223.  
  224.     inbuf = mallocw(BUFSIZ);
  225.     intmp = mallocw(BUFSIZ);
  226.     while ( fgets( inbuf, BUFSIZ, fp ) != NULLCHAR ) {
  227.         strcpy(intmp,inbuf);
  228.         if( (result = cmdparse(dial_cmds,inbuf,ifp)) != 0 ){
  229.             tprintf("input line: %s",intmp);
  230.             break;
  231.         }
  232.     }
  233.     free(inbuf);
  234.     free(intmp);
  235.     fclose(fp);
  236.  
  237.     if ( result == 0 ) {
  238.         ifp->lastsent = ifp->lastrecv = secclock();
  239.     }
  240.  
  241.     ifp->raw = rawsave;
  242.     resume(ifp->rxproc);
  243.     tprintf( "\nDial %s complete\n", ifp->name );
  244.  
  245.     /* Wait for awhile, so the user can read the screen,
  246.      * AND to give it time to send some packets on the new connection!
  247.      */
  248.     pause( 10000L );
  249.     freesession( sp );
  250.     Curproc->input = save_input;
  251.     Curproc->output = save_output;
  252.     return result;
  253. }
  254.  
  255.  
  256. static int
  257. dodial_control(argc,argv,p)
  258. int argc;
  259. char *argv[];
  260. void *p;
  261. {
  262.     struct iface *ifp = p;
  263.     int param;
  264.  
  265.     if ( ifp->ioctl == NULL )
  266.         return -1;
  267.  
  268.     if ( (param = devparam( argv[1] )) == -1 )
  269.         return -1;
  270.  
  271.     (*ifp->ioctl)( ifp, param, TRUE, atol( argv[2] ) );
  272.     return 0;
  273. }
  274.  
  275.  
  276. static int
  277. dodial_send(argc,argv,p)
  278. int argc;
  279. char *argv[];
  280. void *p;
  281. {
  282.     struct iface *ifp = p;
  283.     struct mbuf *bp;
  284.  
  285.     if(argc > 2){
  286.         /* Send characters with inter-character delay
  287.          * (for dealing with prehistoric Micom switches that
  288.          * can't take back-to-back characters...yes, they
  289.          * still exist.)
  290.          */
  291.         char *cp;
  292.         int32 cdelay = atol(argv[2]);
  293.  
  294.         for(cp = argv[1];*cp != '\0';cp++){
  295.             bp = qdata(cp,1);
  296.             asy_send(ifp->dev,bp);
  297.             pause(cdelay);
  298.         }
  299.     } else {
  300.         bp = qdata( argv[1], strlen(argv[1]) );
  301.  
  302.         if (ifp->trace & IF_TRACE_RAW)
  303.             raw_dump( ifp, IF_TRACE_OUT, bp );
  304.         asy_send( ifp->dev, bp );
  305.     }
  306.     return 0;
  307. }
  308.  
  309.  
  310. static int
  311. dodial_speed(argc,argv,p)
  312. int argc;
  313. char *argv[];
  314. void *p;
  315. {
  316.     struct iface *ifp = p;
  317.  
  318.     if ( argc < 2 ) {
  319.         tprintf( "current speed = %u bps\n", Asy[ifp->dev].speed );
  320.         return 0;
  321.     }
  322.     return asy_speed( ifp->dev, (int16)atol( argv[1] ) );
  323. }
  324.  
  325.  
  326. static int
  327. dodial_wait(argc,argv,p)
  328. int argc;
  329. char *argv[];
  330. void *p;
  331. {
  332.     struct iface *ifp = p;
  333.     register int c = -1;
  334.  
  335.     alarm( atol( argv[1] ) );
  336.  
  337.     if ( argc == 2 ) {
  338.         while ( (c = get_asy(ifp->dev)) != -1 ) {
  339.             tputc( c &= 0x7F );
  340.             tflush();
  341.         }
  342.         alarm( 0L );
  343.         return 0;
  344.     } else {
  345.         register char *cp = argv[2];
  346.  
  347.         while ( *cp != '\0'  &&  (c = get_asy(ifp->dev)) != -1 ) {
  348.             tputc( c &= 0x7F );
  349.             tflush();
  350.  
  351.             if (*cp++ != c) {
  352.                 cp = argv[2];
  353.             }
  354.         }
  355.  
  356.         if ( argc > 3 ) {
  357.             if ( stricmp( argv[3], "speed" ) == 0 ){
  358.                 int16 speed = 0;
  359.  
  360.                 while ( (c = get_asy(ifp->dev)) != -1 ) {
  361.                     tputc( c &= 0x7F );
  362.                     tflush();
  363.  
  364.                     if ( isdigit(c) ) {
  365.                         speed *= 10;
  366.                         speed += c - '0';
  367.                     } else {
  368.                         alarm( 0L );
  369.                         return asy_speed( ifp->dev, speed );
  370.                     }
  371.                 }
  372.             } else {
  373.                 return -1;
  374.             }
  375.         }
  376.     }
  377.     alarm( 0L );
  378.     return ( c == -1 );
  379. }
  380.  
  381.  
  382.